package com.example.codeanalysis.parser;


import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;

@Getter
@Setter
@SuppressWarnings("ALL")
public class AnaResult {

  /**
   * 完整类名
   */
  private String clazz;
  /**
   * 类上的API Path
   */
  private String commPath;
  private List<API> apis;

  public AnaResult() {
    this(8);
  }

  public AnaResult(int cap) {
    apis = new ArrayList<>(cap);
  }

  public void add(API api) {
    if (api != null && api.getUrl() != null) {
      if (commPath.endsWith("/") && api.getUrl().startsWith("/")) {
        api.setUrl(this.commPath + api.getUrl().substring(1));
      } else if (!commPath.endsWith("/") && !"".equals(api.getUrl()) && !api.getUrl().startsWith("/")) {
        api.setUrl(this.commPath + "/" + api.getUrl().substring(1));
      } else {
        api.setUrl(this.commPath + api.getUrl());
      }
      this.apis.add(api);
    }
  }

  public void add(String method, String url) {
    this.add(new API(method, url));
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(1024);
    sb.append("\n############\nclass      : ");
    sb.append(this.getClazz());
    sb.append("\ncommonPath : ");
    sb.append(this.getCommPath());
    sb.append("\napis       : ");
    sb.append(this.getApis().size());
    sb.append('\n');
    for (API api : this.getApis()) {
      sb.append("\t- ");
      sb.append(api.toString());
      sb.append('\n');
    }
    return sb.toString();
  }

  @Getter
  public static class API {

    private String method;
    private String url;

    public API(String method, String url) {
      this.method = method;
      if ("/".equals(url)) {
        url = "";
      }
      this.url = url;
    }

    public API() {

    }

    public void setMethod(String method) {
      if ("Request".equals(method)) {
        this.method = "ALL";
      } else {
        this.method = method.toUpperCase(Locale.ROOT);
      }
    }

    public void setUrl(String url) {
      if ("/".equals(url)) {
        url = "";
      }
      this.url = url;
    }


    public void setUrl(List<ASTNode> annValues) {
      for (ASTNode value : annValues) {
        MemberValuePair mvp = (MemberValuePair) value;
        String valueName = mvp.getName().getFullyQualifiedName();
        if ("path".equals(valueName) || "value".equals(valueName)) {
          Expression expression = mvp.getValue();
          if (ASTNode.STRING_LITERAL == expression.getNodeType()) {
            this.url = ((StringLiteral) expression).getLiteralValue().trim();
          }
        }
        if ("method".equals(valueName)) {
          Expression expression = mvp.getValue();
          if (expression instanceof StringLiteral) {
            this.method = ((StringLiteral) expression).getLiteralValue().trim();
          }
          if (expression instanceof QualifiedName) {
            this.method = ((QualifiedName) expression).getName().getFullyQualifiedName();
          }
          if (expression instanceof SimpleName) {
            this.method = ((SimpleName) expression).getFullyQualifiedName();
          }
          if (expression instanceof ArrayInitializer) {
            StringBuilder sb = new StringBuilder();
            List<ASTNode> methods = ((ArrayInitializer) expression).expressions();
            if (methods != null && methods.size() > 0) {
              for (ASTNode method : methods) {
                if (sb.length() > 0) {
                  sb.append(",");
                }
                if (method instanceof QualifiedName) {
                  sb.append(((QualifiedName) method).getName().getFullyQualifiedName());
                } else if (method instanceof SimpleName) {
                  sb.append(((SimpleName) method).getFullyQualifiedName());
                }
              }
            }
            this.method = sb.toString();
          }
        }
      }
    }

    public void setUrl(Expression value) {
      if (ASTNode.STRING_LITERAL == value.getNodeType()) {
        this.url = ((StringLiteral) value).getLiteralValue().trim();
      }
    }

    @Override
    public String toString() {
      return this.method + " " + this.url;
    }
  }
}
